home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / standards / sgml / nist / parse1a / parse1a.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-13  |  15.3 KB  |  461 lines

  1. /* National Institute of Standards and Technology (NIST)
  2. /* National Computer System Laboratory (NCSL)
  3. /* Office Systems Engineering (OSE) Group
  4. /* ********************************************************************
  5. /*                            D I S C L A I M E R
  6. /*                              (March 8, 1989)
  7. /*  
  8. /* There is no warranty for the NIST NCSL OSE SGML parser and/or the NIST
  9. /* NCSL OSE SGML parser validation suite.  If the SGML parser and/or
  10. /* validation suite is modified by someone else and passed on, NIST wants
  11. /* the parser's recipients to know that what they have is not what NIST
  12. /* distributed, so that any problems introduced by others will not
  13. /* reflect on our reputation.
  14. /* 
  15. /* Policies
  16. /* 
  17. /* 1. Anyone may copy and distribute verbatim copies of the SGML source
  18. /* code as received in any medium.
  19. /* 
  20. /* 2. Anyone may modify your copy or copies of SGML parser source code or
  21. /* any portion of it, and copy and distribute such modifications provided
  22. /* that all modifications are clearly associated with the entity that
  23. /* performs the modifications.
  24. /* 
  25. /* NO WARRANTY
  26. /* ===========
  27. /* 
  28. /* NIST PROVIDES ABSOLUTELY NO WARRANTY.  THE SGML PARSER AND VALIDATION
  29. /* SUITE ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
  30. /* EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  31. /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  32. /* THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS
  33. /* WITH YOU.  SHOULD THE SGML PARSER OR VALIDATION SUITE PROVE DEFECTIVE,
  34. /* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  35. /* 
  36. /* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL NIST BE LIABLE FOR
  37. /* DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
  38. /* INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
  39. /* INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
  40. /* BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
  41. /* FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
  42. /* NIST) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF
  43. /* SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
  44. */
  45.  
  46. /************************************************************************/
  47. /*   TITLE:          SGML PARSER                                        */
  48. /*   SYSTEM:         DTD PROCESSOR                                      */
  49. /*   SUBSYSTEM:                                                         */
  50. /*   SOURCE FILE:    PARSE1A.C                                          */
  51. /*   AUTHOR:         Jim Heath                                          */
  52. /*                                                                      */
  53. /*   DATE CREATED:                                                      */
  54. /*   LAST MODIFIED:                                                     */
  55. /*                                                                      */
  56. /*                  REVISIONS                                           */
  57. /*   WHEN      WHO            WHY                                       */
  58. /************************************************************************/
  59. #include   <stdio.h>
  60. #include   <setjmp.h>
  61. #include   <fcntl.h>
  62. #include   <string.h>
  63. #include   <sys/types.h>
  64. #include   <sys/stat.h>
  65. #define    NAMELEN 8
  66. #include   "../incs/dtd.h"
  67. #include   "../incs/parse1a.h"
  68. /* ==================================================================== */
  69. #define CREATOPTS (O_CREAT|O_TRUNC|S_IWRITE|S_IREAD)
  70. /* ==================================================================== */
  71. SYMBREC symbol[MAXNODES];
  72. jmp_buf Xenv;
  73. TREENODE node[MAXNODES];
  74. int next, infile, outfile;
  75. /* ==================================================================== */
  76. main(argc, argv)
  77. int argc;
  78. char *argv[];
  79. {
  80.    int numtokens,firsttoken, root;
  81.    char infname[128], outfname[128];
  82.    DTDREC dtdrec;
  83.    int i, j, k;
  84.    TREENODE *nptr;
  85.  
  86.    strcpy(infname,"dtdfile1.sgm");
  87.    strcpy(outfname,"dtdfile.sgm");
  88.    if ((infile = open("dtdfile1.sgm", O_RDONLY)) == -1){
  89.       printf("unable to open dtdfile1.sgm\n" );
  90.       exit(1);
  91.    }
  92.    if ((outfile = creat("dtdfile.sgm", CREATOPTS)) ==  -1) {
  93.       (void) close(infile);
  94.       printf("unable to create dtdfile.sgm\n");
  95.       exit(1);
  96.    }
  97.  
  98.    if (read(infile, (char *) &numtokens, sizeof(numtokens)) != sizeof(numtokens))
  99.       error("error in reading file");
  100.    if (write(outfile, (char *) &numtokens, sizeof(numtokens)) != sizeof(numtokens))
  101.       error("error in writing file");
  102. #ifdef JDEBUG
  103.    printf("total tokens = %d\n", numtokens);
  104. #endif
  105.    if (read(infile, &firsttoken, sizeof(firsttoken)) != sizeof(firsttoken))
  106.       error("error in reading file");
  107.    if (write(outfile, &firsttoken, sizeof(firsttoken)) != sizeof(firsttoken))
  108.       error("error in writing file");
  109.    bldsymbltbl(numtokens);
  110.    if (setjmp(Xenv) != 0)
  111.       goto DONE;
  112.    for ( j = 0; j < numtokens; j++) {
  113.       memset((char *) node, 0xFF, sizeof(node));
  114.       next = 0;
  115.       root = bldtree();
  116. #ifdef JDEBUG
  117.       for (k = 0; k < next; k++)
  118.          printnode(k);
  119.       getchar();
  120. #endif
  121.       traverse(root);
  122.       for(i = k = 0; k < next; k++) {
  123.          nptr = &node[i++];
  124.          if (nptr->Tinfo == JUNK)
  125.             continue;
  126.          dtdrec.Dtoken = nptr->Tvalue;
  127.          dtdrec.Doi = nptr->Toi;
  128.          dtdrec.Dcontreq = nptr->Tcontext;
  129.          if(write(outfile, &dtdrec, sizeof(dtdrec)) != sizeof(dtdrec))
  130.             error("error in writing file");
  131.          if (nptr->Tvalue == AND)
  132.             if(write(outfile, &nptr->Tandcount, sizeof(nptr->Tandcount)) != sizeof(nptr->Tandcount))
  133.                error("error in writing file");
  134.       }
  135.    }
  136. DONE:
  137.    (void) close(infile);
  138.    (void) close(outfile);
  139.    (void) unlink(infname);
  140. }
  141. /* ==================================================================== */
  142. void bldsymbltbl(numtokens)
  143. int numtokens;
  144. {
  145.    int j;
  146.    char tempname[128];
  147.    for (j = 0; j < numtokens; j++){
  148.       if (j >= (MAXNODES - 1))
  149.          error("overflow while building symbol table");
  150.       if (read(infile, &symbol[j], sizeof(symbol[j])) != sizeof(symbol[j]))
  151.          error("error in reading file");
  152.       if (write(outfile, &symbol[j], sizeof(symbol[j])) != sizeof(symbol[j]))
  153.          error("error in reading file");
  154.       memset(tempname, '\0', sizeof(tempname));
  155.       strncpy(tempname, symbol[j].Sname, 8);
  156.       tempname[8] = '\0';
  157. #ifdef JDEBUG
  158.       if (symbol[j].Smin == 0)
  159.          printf("- - ");
  160.       else if (symbol[j].Smin == 1)
  161.          printf("O - ");
  162.       else if (symbol[j].Smin == 2)
  163.          printf("- O ");
  164.       else if (symbol[j].Smin == 3)
  165.          printf("O O ");
  166.       symbol[j].Sname[NAMELEN - 1] = '\0';
  167.       printf("NAME = %s; tokennbr = %03d\n", tempname, symbol[j].Sid);
  168. #endif
  169.    }
  170. }
  171. /* ==================================================================== */
  172. int bldtree()
  173. {
  174.    DTDREC dtdrec;
  175.    int index, andcount;
  176.    TREENODE *nptr;
  177.  
  178.    if (read(infile, &dtdrec, sizeof(dtdrec)) <= 0)
  179.       longjmp(Xenv, 1);
  180.    else {
  181.       if (next >= (MAXNODES - 1) )
  182.          error("max nodes has been exceeded");
  183.       nptr = &node[index = next++];
  184.       switch(dtdrec.Dtoken) {
  185.       case COMMA:
  186.       case OR:
  187.          nptr->Tvalue = dtdrec.Dtoken;
  188.          nptr->Toi = dtdrec.Doi;
  189.          nptr->Tcontext = dtdrec.Dcontreq;
  190.          nptr->Tleft = bldtree();
  191.          nptr->Tright = bldtree();
  192.          return(index);
  193.       case AND:
  194.          nptr->Tvalue = dtdrec.Dtoken;
  195.          nptr->Toi = dtdrec.Doi;
  196.          nptr->Tcontext = dtdrec.Dcontreq;
  197.          if (read(infile, &nptr->Tandcount, sizeof(nptr->Tandcount)) != sizeof(nptr->Tandcount))
  198.             error("error in file read");
  199. #ifdef OLD
  200.          for (temp = next - 1, j = 0; j < nptr->Tandcount; j++)
  201.             node[temp++].Tleft = bldtree();
  202.          return(index);
  203. #endif
  204.          andcount = nptr->Tandcount;
  205.          while(1) {
  206.             nptr->Tleft = bldtree();
  207.             if(--andcount == 1){
  208.                nptr->Tright = bldtree();
  209.                return(index);
  210.             }
  211.             nptr->Tright = next;
  212.             if (next >= (MAXNODES - 1) )
  213.                error("max nodes has been exceeded");
  214.             nptr = &node[next++];
  215.             nptr->Tvalue = AND;
  216.             nptr->Toi = '1';
  217.             nptr->Tinfo = JUNK;
  218.          }
  219.       case -1:  /* PCDATA */
  220.       case -3:  /* RCDATA */
  221.       case -4:  /* CDATA */
  222.       case -5:  /* EMPTY */
  223.       case -6:  /* ANY */
  224.          nptr->Tvalue = dtdrec.Dtoken;
  225.          nptr->Toi = dtdrec.Doi;
  226.          nptr->Tcontext = dtdrec.Dcontreq;
  227.          nptr->Tleft = nptr->Tright = -1;
  228.          return(index);
  229.       default:
  230.          nptr->Tvalue = dtdrec.Dtoken;
  231.          nptr->Toi = dtdrec.Doi;
  232.          nptr->Tcontext = dtdrec.Dcontreq;
  233.          nptr->Tleft = nptr->Tright = -1;
  234.          return(index);
  235.       }
  236.    }
  237. }
  238. /* ==================================================================== */
  239. void traverse(index)
  240. int index;
  241. {
  242.    TREENODE *nptr = &node[index];
  243.    int retval;
  244.  
  245.    if (ISTERMINAL(nptr->Tvalue)) {
  246.       if (ISOPTIONAL(nptr->Toi))
  247.          nptr->Tcontext = C_NEVERO;
  248.       else if (nptr->Toi == '+')
  249.          nptr->Tcontext = C_FTO;
  250.       else
  251.          nptr->Tcontext = C_ALWAYSO;
  252. #ifdef JDEBUG
  253.       printf("traversing on NODE[%d], %s\n",index, getmsg(nptr->Tcontext));
  254. #endif
  255.    }
  256.    else {
  257.       retval = traverseleft(nptr->Tleft, nptr->Tvalue, nptr->Toi);
  258. #ifdef JDEBUG
  259.       printf("traversing on NODE[%d]\n",index);
  260. #endif
  261.       (void) traverseright(nptr->Tright, nptr->Tvalue, nptr->Toi, retval);
  262.    }
  263. }
  264. /* ==================================================================== */
  265. int traverseleft(index, lastconnector, groupoi)
  266. int index, lastconnector, groupoi;
  267. {
  268.    TREENODE *nptr = &node[index];
  269.    int tempoi, retvalleft, retvalright;
  270.    enum CONTEXT savecontext;
  271.  
  272.    savecontext = nptr->Tcontext;
  273.  
  274.    if (ISTERMINAL(nptr->Tvalue)) {
  275.       if (ISOPTIONAL(nptr->Toi))
  276.          nptr->Tcontext = C_NEVERO;
  277.       else if (lastconnector == AND)
  278.          nptr->Tcontext = C_NEVERO;
  279.       else if (lastconnector == OR)
  280.          nptr->Tcontext = C_NEVERO;
  281.       else if (ISOPTIONAL(groupoi))
  282.          nptr->Tcontext = C_NEVERO;
  283.       else if (groupoi == '+')
  284.          nptr->Tcontext = C_FTO;
  285.       else if (nptr->Toi == '+')
  286.          nptr->Tcontext = C_FTO;
  287.       else
  288.          nptr->Tcontext = C_ALWAYSO;
  289. #ifdef JDEBUG
  290.       printf("traversing on NODE[%d], %s\n",index, getmsg(nptr->Tcontext));
  291. #endif
  292.       /*      nptr->Tcontext = savecontext;*/
  293.       return(nptr->Toi);
  294.    }
  295.  
  296.    tempoi = oifnc(nptr->Toi, nptr->Tvalue, lastconnector, groupoi);
  297.    retvalleft = traverseleft(nptr->Tleft, nptr->Tvalue, tempoi);
  298. #ifdef JDEBUG
  299.    printf("traversing on NODE[%d]\n",index);
  300. #endif
  301.    retvalright = traverseright(nptr->Tright, nptr->Tvalue, tempoi, retvalleft);
  302.    return(reqmntfnc(nptr->Tvalue, nptr->Toi, retvalleft, retvalright));
  303. }
  304. /* ==================================================================== */
  305. int traverseright(index, lastconnector, groupoi, leftoi)
  306. int index, lastconnector, groupoi, leftoi;
  307. {
  308.    TREENODE *nptr = &node[index];
  309.    int retvalleft, retvalright;
  310.    enum CONTEXT savecontext;
  311.  
  312.    savecontext = nptr->Tcontext;
  313.    if (ISTERMINAL(nptr->Tvalue)) {
  314.       if ((lastconnector == OR) || (lastconnector == AND))
  315.          nptr->Tcontext = C_NEVERO;
  316.       else if (ISOPTIONAL(nptr->Toi))
  317.          nptr->Tcontext = C_NEVERO;
  318.       else if (ISOPTIONAL(leftoi)) {
  319.          if (ISOPTIONAL(groupoi))
  320.             nptr->Tcontext = C_SOMETIMESO;
  321.          else if (groupoi == '+')
  322.             nptr->Tcontext = C_FTOTSO;
  323.          else if (groupoi == '1')
  324.             nptr->Tcontext = C_ALWAYSO;
  325.       }
  326.       /* leftoi is not optional */
  327.       else if ((groupoi == '+') && (nptr->Toi == '+'))
  328.          nptr->Tcontext = C_FTOWR;
  329.       else if (nptr->Toi == '+')
  330.          nptr->Tcontext = C_FTO;
  331.       else
  332.          nptr->Tcontext = C_ALWAYSO;
  333.  
  334. #ifdef JDEBUG
  335.       printf("traversing on NODE[%d], %s\n",index, getmsg(nptr->Tcontext));
  336. #endif
  337.       /*      nptr->Tcontext = savecontext;*/
  338.       return(nptr->Toi);
  339.    }
  340.    retvalleft = traverseleft(nptr->Tleft, nptr->Tvalue, nptr->Toi);
  341. #ifdef JDEBUG
  342.    printf("traversing on NODE[%d]\n",index);
  343. #endif
  344.    retvalright = traverseright(nptr->Tright, nptr->Tvalue, nptr->Toi, retvalleft);
  345.    return(reqmntfnc(nptr->Tvalue, nptr->Toi, retvalleft, retvalright));
  346. }
  347. /* ==================================================================== */
  348. int oifnc(curroi, currval, lastconnector, prevoi)
  349. int curroi, currval, lastconnector, prevoi;
  350. {
  351.    if ((lastconnector == AND) || (lastconnector == OR))
  352.       return('?');
  353.    if (ISOPTIONAL(prevoi) && (currval == COMMA))
  354.       return(prevoi);
  355.    if ((currval == AND) || (currval == OR))
  356.       return('?');
  357.    return(curroi);
  358. }
  359. /* ==================================================================== */
  360. void printnode(k)
  361. int k;
  362. {
  363.    TREENODE *nptr = &node[k];
  364.    char tvalue[16];
  365.    switch (nptr->Tvalue) {
  366.    case COMMA:
  367.       strcpy(tvalue, "COMMA");
  368.       break;
  369.    case OR:
  370.       strcpy(tvalue, "OR");
  371.       break;
  372.    case AND:
  373.       strcpy(tvalue, "AND");
  374.       break;
  375.    default:
  376.       printf("NODE[%d] left = %d, right = %d, value = %s, oi = %c\n",
  377.           k, nptr->Tleft, nptr->Tright, symbol[nptr->Tvalue].Sname, nptr->Toi);
  378.       return;
  379.    }
  380.    printf("NODE[%d] left = %d, right = %d, value = %s, oi = %c\n",
  381.        k, nptr->Tleft, nptr->Tright, tvalue, nptr->Toi);
  382. }
  383. /* ==================================================================== */
  384.  
  385. /*----------------------------------------------*/
  386. /*           HEADING            */
  387. /*  Simply prints a informatory heading */
  388. /*  when the document parser is invoked */
  389. /*  describing the document name to be  */
  390. /*  parsed.                 */
  391. /*----------------------------------------------*/
  392.  
  393. void heading()
  394. {
  395.    printf("\n                          DTDFILE Decoder\n");
  396.    printf("                      Decodes DTDFILES built by PARSE2\n");
  397.    printf("          --------------------------------------------------\n");
  398.    printf("                      03Nov86      Version 1.01\n");
  399.    printf("          --------------------------------------------------\n\n");
  400.    return;
  401. }
  402. /* ==================================================================== */
  403. void error(msg)
  404. char *msg;
  405. {
  406.    (void) close(infile);
  407.    (void) close(outfile);
  408.    printf(msg);
  409.    exit(1);
  410. }
  411. /* ==================================================================== */
  412. void doopts(argc, argv, infname, outfname)
  413. int argc;
  414. char *argv[];
  415. char *infname, *outfname;
  416. {
  417. }
  418. /* ==================================================================== */
  419. char *getmsg(x)
  420. enum CONTEXT x;
  421. {
  422.    switch (x) {
  423.    case C_NEVERO:
  424.       return("<start tag is never omissable>");
  425.    case C_ALWAYSO:
  426.       return("<start tag is always omissable>");
  427.    case C_SOMETIMESO:
  428.       return("<start tag is sometimes omissable>");
  429.    case C_FTO:
  430.       return("<start tag is omissable first time only>");
  431.    case C_FTOWR:
  432.       return("<start tag is omissable FTO with reset>");
  433.    case C_FTOTSO:
  434.       return("<start tag is omissable FTO then sometimes>");
  435.    default:
  436.       return("UNKNOWN ARGUMENT TO GETMSG()");
  437.    }
  438. }
  439. /* ==================================================================== */
  440. int reqmntfnc(connector, oi, oileft, oiright)
  441. int connector, oileft, oiright;
  442. {
  443.    if(ISOPTIONAL(oi))
  444.       return(oi);
  445.    switch (connector) {
  446.    case COMMA:
  447.    case AND:
  448.       if(ISOPTIONAL(oileft) && ISOPTIONAL(oiright))
  449.          return'?';
  450.       return(oi);
  451.    case OR:
  452.       if(ISOPTIONAL(oileft) || ISOPTIONAL(oiright))
  453.          return'?';
  454.       return(oi);
  455.    default:
  456.       printf("illegal value to reqmntfnc()\n");
  457.       exit(1);
  458.    }
  459. }
  460.  
  461.